package com.wugh.fast.kernel.util;

import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ReflectUtil;
import com.wugh.fast.kernel.core.exception.FastGlobalException;
import com.wugh.fast.kernel.util.exception.FastCopyException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 说明: 拷贝工具类
 *
 * @author wugh
 * @date 2019-01-24 20:31
 */
public class CopyUtils {
    /**
     * 工具类私有构造方法
     */
    private CopyUtils() {
    }

    private static CopyOptions copyOptions;

    static {
        copyOptions = new CopyOptions();
        copyOptions.setIgnoreError(true);

    }

    public static <T> T copyObject(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        if (targetClass == null) {
            throw new FastGlobalException("目标字节码为为空");
        }
        T t = ReflectUtil.newInstance(targetClass);
        copyObject(source, t);
        return t;
    }

    public static void copyObject(Object source, Object target) {
        if (source == null) {
            throw new FastCopyException("复制的源对象不能为空");
        }
        if (target == null) {
            throw new FastCopyException("复制的目标对象不能为空");
        }
        cn.hutool.core.bean.BeanUtil.copyProperties(source, target, copyOptions);
    }

    public static <T> List<T> copyCollection(Collection sourceCollection, Class<T> targetClass) {
        if (sourceCollection == null) {
            return null;
        }
        if (targetClass == null) {
            throw new FastCopyException("目标字节码为为空");
        }
        if (sourceCollection.isEmpty()) {
            return new ArrayList<>(0);
        }
        return (List<T>) sourceCollection.stream().map(source -> copyObject(source, targetClass)).collect(Collectors.toList());
    }

    private static <T> void copyCollection(Collection<?> sourceCollection, Collection<T> targetCollection, Class<T> targetClass) {
        sourceCollection
                .stream()
                .filter(Objects::nonNull)
                .forEach(source -> {
                    targetCollection.add(copyObject(source, targetClass));
                });
    }
}
